package com.code.helpers;

import com.code.consts.HeaderConstants;
import com.code.utils.CookieUtil;
import com.code.utils.RequestContextUtil;
import com.code.utils.StringUtil;
import org.apache.commons.codec.digest.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * 登录TOKEN辅助类
 * 备注：
 * 1、对于登陆token，变化成本高的token不要轻易变化
 * 2、不轻易变化的token要减少曝光频率（网络传输次数）
 * 3、曝光频率高的token的生存周期要尽量短(比如会话token，移动端平台是个人用户极其私密的平台，它人接触的机会不大，移动端生存周期长；由于web登录环境一般很可能是公共环境，被他人盗取的风险值较大，Web平台生存周期短)
 * 对于token的具体细节可以参考<a href="https://mp.weixin.qq.com/s/_-JWSPGjZq2p1rCIbP3snQ">基于 token 的多平台身份认证架构设计</a>
 *
 * @author xiaoyaowang
 * @since 2019-5-24 10:41:31
 */
public class LoginTokenHelper {

    private final static String SECRET_KEY = "Ld4Dl5f9OoYTezPK";

    private final static String LOGIN_TOKEN_KEY = "LOGIN-TOKEN";

    /**
     * 根据登录的相关信息生成TOKEN ID
     *
     * @param loginAccount 登录账号
     * @param ip           登录IP
     * @param platform     登录平台
     * @param loginTime    登录时间
     * @param ttl          生存时长(单位：秒)
     * @return 根据登录的相关信息生成TOKEN ID
     */
    public static String generateId(String loginAccount,
                                    String ip, String platform, Date loginTime, long ttl) {
        StringBuilder noEncodeLoginTokenId = new StringBuilder(loginAccount)
                .append(ip)
                .append(platform)
                .append(loginTime)
                .append(ttl);

        return DigestUtils.sha256Hex(SECRET_KEY + DigestUtils.md5Hex(noEncodeLoginTokenId.toString()) + DigestUtils.md5Hex(SECRET_KEY));
    }

    /**
     * 添加登录TOKEN的ID信息到COOKIE中
     *
     * @param loginTokenId   登录的token id
     * @param expiredTimeSec 生存时长
     */
    public static void addLoginTokenIdToCookie(String loginTokenId, Integer expiredTimeSec) {
        HttpServletResponse response = RequestContextUtil.getResponse();
        CookieUtil.addCookie(response, HeaderConstants.X_TOKEN, loginTokenId, null == expiredTimeSec ? -1 : expiredTimeSec, true);
    }

    /**
     * 从COOKIE中清理登录账号信息
     */
    public static void delLoginTokenIdFromCookie() {
        HttpServletRequest request = RequestContextUtil.getRequest();
        HttpServletResponse response = RequestContextUtil.getResponse();

        CookieUtil.delCookie(request, response, HeaderConstants.X_TOKEN);
    }

    /**
     * 从请求头中或者从浏览器的cookie中获取登录的TOKEN的ID
     *
     * @return 登录token
     */
    public static String getLoginTokenId() {
        HttpServletRequest request = RequestContextUtil.getRequest();
        String token = request.getHeader(HeaderConstants.X_TOKEN);
        if (StringUtil.isEmpty(token)) {
            token = CookieUtil.getCookieValue(request, HeaderConstants.X_TOKEN, true);
        }
        return token;
    }

}
